using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace EasyEditorGUI.Editor
{
    public static class Extensions
    {
        public static string GetHexString(this SerializedProperty property, byte size)
        {
            return property.longValue.ToString($"x{size / 4}");
        }
        
        public static void BitArrayGUI(this SerializedProperty property, 
            in Rect position, 
            byte width,
            byte bitWide,
            bool reverse = false,
            bool showHexValue = false, 
            bool hexValueAsLabel = false)
        {
            var pos = EditorGUI.PrefixLabel(position,
                new GUIContent(hexValueAsLabel ? property.GetHexString(bitWide) : property.displayName));

            float height = EditorGUI.GetPropertyHeight(property);
            pos.height = height;
            pos.width = height;

            float x = pos.x;
            for (int i = 0; i < bitWide; i++)
            {
                long value = property.longValue;
                int offset = reverse ? width - i % width - 1 + i / width * width : i;
                bool b = Convert.ToBoolean((value >> offset) & 1);
                bool ret = EditorGUI.Toggle(pos, b, EditorStyles.radioButton);
                if (ret != b)
                {
                    value ^= 1L << offset;
                    property.longValue = value;
                    property.serializedObject.ApplyModifiedProperties();
                }

                if ((i + 1) % width == 0)
                {
                    pos.x = x;                    
                    pos.y += height;
                }
                else
                {
                    pos.x += height;
                }
            }

            if (showHexValue)
            {
                pos.x += height * width;
                pos.y = position.y;
                pos.width = position.width - height * width;
                EditorGUI.LabelField(pos, property.GetHexString(bitWide));
            }
        }

        public static void SetDropDownValue(this SerializedProperty property, IReadOnlyList<string> options, int index)
        {
            if (property.propertyType == SerializedPropertyType.String)
            {
                property.stringValue = options[index];
            }
            else if (property.propertyType == SerializedPropertyType.Integer)
            {
                property.intValue = index;
            }
        }

        public static int GetDropDownIndex(this SerializedProperty property, string[] options)
        {
            if (property.propertyType == SerializedPropertyType.String)
            {
                return Array.IndexOf(options, property.stringValue);
            }

            if (property.propertyType == SerializedPropertyType.Integer)
            {
                return property.intValue;
            }

            return -1;
        }
        
        /// <summary>
        /// 显示一个下拉选择菜单
        /// </summary>
        /// <param name="position"></param>
        /// <param name="label">自定义标签</param>
        /// <param name="property">string类型property</param>
        /// <param name="options"></param>
        public static void DropDownGUI(this SerializedProperty property, in Rect position, string label, string[] options)
        {
            property.DropDownGUI(position, label, options, options);
        }

        public static void DropDownGUI(this SerializedProperty property, in Rect position, string[] options)
        {
            property.DropDownGUI(position, property.displayName, options);    
        }

        public static void DropDownGUI(this SerializedProperty property, in Rect position, string label, string[] optionDisplayNames,
            string[] optionValues)
        {
            if (optionDisplayNames.Length != optionValues.Length)
            {
                throw new Exception($"{nameof(optionDisplayNames)}.Length != {nameof(optionValues)}.Length");
            }
            
            int index = property.GetDropDownIndex(optionValues);
            if (index < 0)
            {
                index = 0;
                property.SetDropDownValue(optionValues, index);
                property.serializedObject.ApplyModifiedProperties();
            }
                        
            using (var cc = new EditorGUI.ChangeCheckScope())
            {
                index = EditorGUI.Popup(position, label, index, optionDisplayNames);
                if (!cc.changed) return;
                property.SetDropDownValue(optionValues, index);
                property.serializedObject.ApplyModifiedProperties();
            }   
        }

        public static void DropDownGUI(this SerializedProperty property, in Rect position, string[] optionDisplayNames,
            string[] optionValues)
        {
            property.DropDownGUI(position, property.displayName, optionDisplayNames, optionValues);    
        }
    }
}